package com.estore.service;

import com.estore.model.Product;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.*;
import java.util.Properties;

/**
 * 商品服务类，负责商品相关的业务逻辑
 * 支持数据持久化到文件，支持配置文件管理
 */
public class ProductService {

    // 使用Map存储商品数据，key是商品ID，value是商品对象
    // 优点：通过ID查找商品时，时间复杂度是O(1)，非常高效
    private final Map<String, Product> productData = new HashMap<>();

    // 配置属性
    private String dataFilePath;
    private String fileEncoding;

    // 默认配置值
    private static final String DEFAULT_DATA_FILE = "products.dat";
    private static final String DEFAULT_ENCODING = "UTF-8";
    private static final String CONFIG_FILE = "config.properties";

    /**
     * 构造函数，初始化商品数据
     * 优先从文件加载，如果文件不存在则使用默认数据
     */
    public ProductService() {
        // 先加载配置
        loadConfig();

        // 然后加载商品数据
        if (!loadData()) {
            // 如果加载数据失败，使用默认数据
            initializeDefaultData();
        }
    }

    /**
     * 加载配置文件
     */
    private void loadConfig() {
        Properties props = new Properties();
        File configFile = new File(CONFIG_FILE);

        if (!configFile.exists()) {
            System.out.println("配置文件不存在，使用默认配置");
            dataFilePath = DEFAULT_DATA_FILE;
            fileEncoding = DEFAULT_ENCODING;
            return;
        }

        try (InputStreamReader reader = new InputStreamReader(
                new FileInputStream(CONFIG_FILE), "UTF-8")) {

            props.load(reader);

            // 读取数据文件路径，如果配置为空则使用默认值
            dataFilePath = props.getProperty("data.file.path", DEFAULT_DATA_FILE);
            fileEncoding = props.getProperty("file.encoding", DEFAULT_ENCODING);

            System.out.println("配置文件加载成功");
            System.out.println("数据文件路径: " + dataFilePath);
            System.out.println("文件编码: " + fileEncoding);

        } catch (IOException e) {
            System.err.println("加载配置文件失败: " + e.getMessage() + "，使用默认配置");
            dataFilePath = DEFAULT_DATA_FILE;
            fileEncoding = DEFAULT_ENCODING;
        }
    }

    /**
     * 初始化默认商品数据
     */
    private void initializeDefaultData() {
        productData.put("p001", new Product("p001", "Java从入门到精通", 99.0, 100));
        productData.put("p002", new Product("p002", "高性能MySQL", 128.5, 50));
        productData.put("p003", new Product("p003", "颈椎康复指南", 45.0, 200));
        productData.put("p004", new Product("p004", "生发秘籍", 88.0, 0)); // 库存为0的商品
        System.out.println("使用默认商品数据初始化完成");
    }

    /**
     * 保存商品数据到文件
     * @return 保存成功返回true，失败返回false
     */
    public boolean saveData() {
        // 确保数据文件目录存在
        ensureDirectoryExists(dataFilePath);

        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(dataFilePath))) {
            oos.writeObject(productData);
            System.out.println("商品数据已保存到文件: " + dataFilePath);
            return true;
        } catch (IOException e) {
            System.err.println("保存商品数据失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 从文件加载商品数据
     * @return 加载成功返回true，失败返回false
     */
    @SuppressWarnings("unchecked")
    private boolean loadData() {
        File file = new File(dataFilePath);
        if (!file.exists()) {
            System.out.println("数据文件不存在，将使用默认数据");
            return false;
        }

        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(dataFilePath))) {
            Object obj = ois.readObject();
            if (obj instanceof Map) {
                productData.clear();
                productData.putAll((Map<String, Product>) obj);
                System.out.println("从文件加载商品数据成功，共 " + productData.size() + " 个商品");
                return true;
            }
        } catch (IOException | ClassNotFoundException e) {
            System.err.println("加载商品数据失败: " + e.getMessage());
        }
        return false;
    }

    /**
     * 确保文件所在目录存在
     * @param filePath 文件路径
     */
    private void ensureDirectoryExists(String filePath) {
        File file = new File(filePath);
        File parentDir = file.getParentFile();

        if (parentDir != null && !parentDir.exists()) {
            if (parentDir.mkdirs()) {
                System.out.println("创建目录: " + parentDir.getAbsolutePath());
            }
        }
    }

    /**
     * 获取所有商品列表
     * @return 商品列表
     */
    public List<Product> getAllProducts() {
        // 从Map的值集合创建一个新的ArrayList并返回
        return new ArrayList<>(productData.values());
    }

    /**
     * 根据ID查找商品
     * @param id 商品ID
     * @return 找到的商品对象，如果不存在则返回null
     */
    public Product findProductById(String id) {
        return productData.get(id);
    }

    /**
     * 添加或更新商品
     * @param product 商品对象
     */
    public void saveProduct(Product product) {
        productData.put(product.getId(), product);
    }

    /**
     * 删除商品
     * @param id 商品ID
     */
    public void deleteProduct(String id) {
        productData.remove(id);
    }

    /**
     * 获取商品数量
     * @return 商品总数
     */
    public int getProductCount() {
        return productData.size();
    }

    /**
     * 获取当前配置的数据文件路径（用于测试和显示）
     * @return 数据文件路径
     */
    public String getDataFilePath() {
        return dataFilePath;
    }

    /**
     * 获取当前配置的文件编码（用于测试和显示）
     * @return 文件编码
     */
    public String getFileEncoding() {
        return fileEncoding;
    }
    /**
     * 备份数据文件
     * @return 备份成功返回true，失败返回false
     */
    public boolean backupData() {
        String sourceFilePath = dataFilePath;
        String backupFilePath = sourceFilePath + ".bak";

        File sourceFile = new File(sourceFilePath);
        if (!sourceFile.exists()) {
            System.out.println("错误：源数据文件不存在，无法备份！");
            return false;
        }

        try (FileInputStream fis = new FileInputStream(sourceFile);
             FileOutputStream fos = new FileOutputStream(backupFilePath)) {

            byte[] buffer = new byte[1024];
            int bytesRead;
            long totalBytes = 0;

            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }

            fos.flush();
            System.out.println("数据备份完成: " + backupFilePath + " (" + totalBytes + " 字节)");
            return true;

        } catch (IOException e) {
            System.err.println("备份数据失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 检查备份文件是否存在
     * @return 备份文件存在返回true，否则返回false
     */
    public boolean isBackupExists() {
        File backupFile = new File(dataFilePath + ".bak");
        return backupFile.exists();
    }

    /**
     * 从备份文件恢复数据
     * @return 恢复成功返回true，失败返回false
     */
    public boolean restoreFromBackup() {
        String backupFilePath = dataFilePath + ".bak";
        File backupFile = new File(backupFilePath);

        if (!backupFile.exists()) {
            System.out.println("错误：备份文件不存在，无法恢复！");
            return false;
        }

        try (FileInputStream fis = new FileInputStream(backupFile);
             FileOutputStream fos = new FileOutputStream(dataFilePath)) {

            byte[] buffer = new byte[1024];
            int bytesRead;
            long totalBytes = 0;

            while ((bytesRead = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }

            fos.flush();
            System.out.println("数据恢复完成: " + totalBytes + " 字节");

            // 重新加载恢复的数据
            return loadData();

        } catch (IOException e) {
            System.err.println("恢复数据失败: " + e.getMessage());
            return false;
        }
    }
}